import tempfile
from copy import copy
from datetime import datetime

import pytz
from django.core.paginator import Paginator
from django.http import HttpResponse
from django.shortcuts import render
from django.apps import apps
# Create your views here.
from django.db.models.expressions import RawSQL
from django.utils.dateparse import parse_datetime
from rest_framework import status
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.permissions import BasePermission
from rest_framework.response import Response
from rest_framework.views import APIView
from docx import Document
from CourseAdjustmentManagement.serializers import TeacherChangeClassRecordSerializer, ClassroomScheduleSerializer
from CourseAdjustmentManagement.models import *  # 或者显式导入每个模型类
from CourseAdjustmentManagement.views.public_data import our_classroom


def get_model_fields_info(model_class):
    fields_info = {'model_name': model_class._meta.verbose_name}

    for field in model_class._meta.get_fields(include_hidden=True):
        # 获取字段的基本信息
        field_name = field.name
        field_type = field.__class__.__name__
        verbose_name = field.verbose_name

        # 获取choices信息，如果有的话
        choices = None
        if hasattr(field, 'choices') and field.choices:
            choices = field.choices
            # 提取每个子数组的第一个元素
            choices = [sublist[0] for sublist in choices]

        # 将信息存入字典
        fields_info[field_name] = {
            'type': field_type,
            'verbose_name': verbose_name,
            'choices': choices,
        }

    return fields_info


# 获取所有模型类
CourseAdjustment_manager_config = apps.get_app_config('CourseAdjustmentManagement')
model_classes = CourseAdjustment_manager_config.get_models()
# 构建模型信息字典

model_info_dict = {model.__name__: get_model_fields_info(model) for model in model_classes}

# 权限管理
"""
reviewer:可以审核所有report
TDAdmin:可以审核所有report，并且可以添加和删除report
"""


class IsReviewer(BasePermission):

    def has_permission(self, request, view):
        # 假设您有一个名为 'reviewer' 的用户组

        return request.user.groups.filter(name='reviewer').exists()


class IsTDAdmin(BasePermission):
    def has_permission(self, request, view):
        # 假设您有一个名为 'TDAdmin' 的用户组

        return request.user.groups.filter(name='TDAdmin').exists()


# 创建
class CreateView(APIView):
    # 定义一个Report字段为空对象
    model = None
    Serializer = None

    def post(self, request):
        # 判断是否request.user.name ==request.data.name
        # 如果是，则继续处理POST请求
        # 返回所有TrainingReport满足 TrainingReport.objects.author[0]==request.user.name的条目
        # 如果不是，则返回错误信息
        try:
            # 获取字段从而知道操作哪个模型类与序列化类

            self.model = TeacherChangeClassRecord
            self.Serializer = TeacherChangeClassRecordSerializer
            request.data['teacher_id'] = request.user.username
            request.data['teacher_name'] = request.user.name
            return self.get_reports(request)
        except Exception as e:
            return Response({'error': 'Invalid data:' + str(e)}, status=status.HTTP_400_BAD_REQUEST)

    def get_reports(self, request):
        # 将request.data中的数据序列化后添加到model中。
        serializer = self.Serializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({'success': 'Report created successfully'}, status=201)
        else:
            return Response({'error': 'Invalid data:' + str(serializer.errors)}, status=400)


# 删除条目
class DeleteView(APIView):
    model = None
    Serializer = None

    def post(self, request):
        # 判断是否request.user.name ==request.data.name
        # 如果是，则继续处理POST请求
        # 返回所有TrainingReport满足 TrainingReport.objects.author[0]==request.user.name的条目
        # 如果不是，则返回错误信息
        try:
            # 获取字段从而知道操作哪个模型类与序列化类
            self.model = TeacherChangeClassRecord
            self.Serializer = TeacherChangeClassRecordSerializer
            report = self.model.objects.get(id=request.data['id'])
            if request.user.username != report.teacher_id:
                return Response({'error': '这不是你的数据，禁止删除'}, status=403)
            elif report.revstatus == '已批准':
                return Response({'error': '批准后不允许修改'}, status=403)
            else:
                return self.get_reports(report)
        except Exception as e:
            return Response({'error': 'Invalid data:' + str(e)}, status=400)

    def get_reports(self, report):
        # 获取id，根据id删除该条目
        report.delete()
        return Response({'success': '数据已经删除'}, status=200)


# 修改条目
class UpdateView(APIView):
    model = None
    Serializer = None

    def post(self, request):
        # 判断是否request.user.name ==request.data.name
        # 如果是，则继续处理POST请求
        # 返回所有TrainingReport满足 TrainingReport.objects.author[0]==request.user.name的条目
        # 如果不是，则返回错误信息
        try:
            self.model = TeacherChangeClassRecord
            self.Serializer = TeacherChangeClassRecordSerializer
            report = self.model.objects.get(id=request.data['id'])
            if request.user.username != report.teacher_id:
                return Response({'error': '你不是这个数据的责任人，无法修改'}, status=403)
            elif report.revstatus == '已批准':
                return Response({'error': '已经通过审核无法修改，请联系管理员'}, status=403)
            else:
                return self.get_reports(request, report)
        except Exception as e:
            return Response({'error': 'Invalid data: ' + str(e)}, status=400)

    def get_reports(self, request, report):
        # 获取id，根据id修改该条目,用序列化

        serializer = self.Serializer(report, data=request.data)
        if serializer.is_valid():
            serializer.save()
            # 修改一下 审核状态并再次保存
            report.revstatus = '待审批'
            report.save()
            return Response({'success': '调课信息修改成果，请等待批准'}, status=200)
        else:
            return Response({'error': '提交了无效数据:' + str(serializer.errors)}, status=400)


# 获取所有条目
class GetView(APIView):
    model = None
    Serializer = None

    def post(self, request):
        # 判断是否request.user.name ==request.data.name
        # 如果是，则继续处理POST请求
        # 返回所有TrainingReport满足 TrainingReport.objects.author[0]==request.user.name的条目
        # 如果不是，则返回错误信息
        # try:
        try:
            self.model = TeacherChangeClassRecord
            self.Serializer = TeacherChangeClassRecordSerializer
            return self.get_reports(request)
        except Exception as e:
            return Response({'error': '无效数据: ' + str(e)}, status=400)

    # except Exception as e:
    #     return Response({'error': 'Invalid data:' + str(e)}, status=400)

    def get_reports(self, request):
        # 根据id返回TrainingReport
        reports = self.filter_reports_by_user(request)
        reports = self.filter_reports_by_time(request, reports)
        total_datas = len(reports)

        if request.data['page']:
            # 创建分页器实例，每页显示10条记录
            paginator = Paginator(reports, 10)
            # 获取当前页面
            page_number = request.data['page']
            reports = paginator.get_page(page_number)

        serializer = self.Serializer(reports, many=True, context={'request': request})
        return Response({'total_datas': total_datas, 'datas': serializer.data}, status=200)

    def filter_reports_by_user(self, request):
        username = request.user.username
        # 筛选所有teacher_id==username是实例
        reports = self.model.objects.filter(teacher_id=username)

        return reports

    def filter_reports_by_time(self, request, reports):
        start_time = request.data.get('start_time')
        end_time = request.data.get('end_time')
        if not start_time or not end_time:
            return Response({"error": "请提供 start_time 和 end_time 参数"}, status=status.HTTP_400_BAD_REQUEST)
        # 处理时间字符串
        start_time = parse_datetime(start_time)
        end_time = parse_datetime(end_time)
        #添加Z时区
        start_time = start_time.replace(tzinfo=timezone.utc)
        end_time = end_time.replace(tzinfo=timezone.utc)

        # 应用时间范围过滤
        reports = reports.filter(created_at__range=(start_time, end_time))

        return reports


# 增：上传附件
class AddFileView(APIView):
    parser_classes = [MultiPartParser, FormParser]  # 添加支持multipart/form-data的解析器
    model = None
    Serializer = None

    def post(self, request):
        # 判断是否request.user.name ==request.data.name
        # 如果是，则继续处理POST请求
        # 返回所有TrainingReport满足 TrainingReport.objects.author[0]==request.user.name的条目
        # 如果不是，则返回错误信息
        try:
            self.model = TeacherChangeClassRecord
            self.Serializer = TeacherChangeClassRecordSerializer
            report = self.model.objects.get(id=request.data['id'])
            if request.user.username != report.teacher_id:
                return Response({'error': '你不是这个数据的责任人，不可操作'}, status=status.HTTP_403_FORBIDDEN)
            else:
                return self.get_reports(request, report)

        except Exception as e:
            return Response({'error': '无效数据 : ' + str(e)}, status=400)

    def get_reports(self, request, report):
        # 上传附件信息
        # 获取上传的文件对象
        try:
            uploaded_file = request.FILES.get('file')  # 尝试从请求中获取文件

            if uploaded_file:
                # 如果有文件被上传，将其保存到报告的attachment字段
                report.attachment = uploaded_file
                report.save()
                return Response({"message": "上传文件成功."}, status=status.HTTP_200_OK)
            else:
                return Response({"message": "没有文件被上传."}, status=status.HTTP_400_BAD_REQUEST)

        except Exception as e:
            return Response({"message": "上传文件失败: " + str(e)}, status=status.HTTP_400_BAD_REQUEST)


# 查询所有模型字段
class GetModelFieldsView(APIView):
    def post(self, request):
        # 返回model_info_dict
        try:
            fields = model_info_dict
            fields['TeacherChangeClassRecord']['new_room']['choices'] = our_classroom

            return Response(fields, status=status.HTTP_200_OK)
        except Exception as e:
            return Response({"message": "获取字段失败：" + str(e)}, status=status.HTTP_400_BAD_REQUEST)


# 获取能用的教室
class GetCanUseView(APIView):
    model = None
    Serializer = None

    def post(self, request):
        # 判断是否request.user.name ==request.data.name
        # 如果是，则继续处理POST请求
        # 返回所有TrainingReport满足 TrainingReport.objects.author[0]==request.user.name的条目
        # 如果不是，则返回错误信息
        # try:
        # try:
        self.model = ClassroomSchedule
        self.Serializer = ClassroomScheduleSerializer
        return self.get_reports(request)

    # except Exception as e:
    #     return Response({'error': 'Invalid data:' + str(e)}, status=400)

    # except Exception as e:
    #     return Response({'error': 'Invalid data:' + str(e)}, status=400)

    def get_reports(self, request):
        # 根据id返回TrainingReport
        # 获取原课表中不能用的教室
        org_NO_classroom = self.filter_reports_org(request)
        # 获取调课表中不能用的教室
        change_NO_classroom = self.filter_reports_change(request)
        can_use_room = list(set(our_classroom) - set(org_NO_classroom) - set(change_NO_classroom))
        # 将里面的字符串元素排序
        can_use_room.sort()

        # 获取调课记录中不能用的教室

        return Response({'can_use_room': can_use_room}, status=200)

    def filter_reports_org(self, request):
        reports = self.model.objects.filter(term=request.data.get('term'))
        reports = reports.filter(week=request.data.get('week'))
        new_reports = []
        new_class_time = request.data.get('new_class_time')
        # 判断时间段是否冲突
        self_day, class_range_str = new_class_time.split('/')
        self_start_class, self_end_class = class_range_str.split('-')
        for report in reports:
            report_day, record_class_range_str = report.new_class_time.split('/')
            report_start_class, report_end_class = record_class_range_str.split('-')

            if self_day == report_day:
                if int(self_end_class) < int(report_start_class) or (int(self_start_class) > int(report_end_class)):
                    pass
                else:
                    new_reports.append(report)
        # 获取所有new_reports的教室名
        classroom = [report.classroom_name for report in new_reports]
        return classroom

    def filter_reports_change(self, request):
        # 获取这些记录的教室名
        new_reports = []
        conflict_reports = TeacherChangeClassRecord.objects.filter(new_week=request.data.get('week'),
                                                           term=request.data.get('term'))
        new_class_time = request.data.get('new_class_time')
        # 判断时间段是否冲突
        self_day, class_range_str = new_class_time.split('/')
        self_start_class, self_end_class = class_range_str.split('-')
        for report in conflict_reports:
            report_day, record_class_range_str = report.new_class_time.split('/')
            report_start_class, report_end_class = record_class_range_str.split('-')

            if self_day == report_day:
                if int(self_end_class) < int(report_start_class) or (int(self_start_class) > int(report_end_class)):
                    pass
                else:
                    new_reports.append(report)
        # 获取所有new_reports的教室名
        classroom = [report.new_room for report in new_reports]
        return classroom


# 导出到word文件
class DownloadWordView(APIView):
    Serializer = None
    model = None

    def post(self, request):
        try:
            # 获取字段从而知道操作哪个模型类与序列化类
            self.model = TeacherChangeClassRecord
            self.Serializer = TeacherChangeClassRecordSerializer
            report = self.model.objects.get(id=request.data['id'])
            if request.user.username != report.teacher_id:
                return Response({'error': '这不是你的数据，禁止导出'}, status=403)
            elif report.revstatus != '已批准':
                return Response({'error': '未批准的数据不允许导出'}, status=403)
            else:
                return self.get_reports(report)
        except Exception as e:
            return Response({'error': '无效数据:' + str(e)}, status=400)

    def get_reports(self, report):
        # 加载模板文档
        doc = Document('Files/FileTemplate/调课表新版.docx')  # 替换为模板文档的实际路径
        # 将updated_at的时间转为 xxxx年x月x日 字符串
        data = {
            'term': report.term,  # 替换为实际数据
            'teacher_name': report.teacher_name,  # 替换为实际数据
            'course_name': report.course_name,  # 替换为实际数据
            'reason': report.reason,  # 替换为实际数据
            'original_week': report.original_week,  # 替换为实际数据
            'original_class_time': report.original_class_time,  # 替换为实际数据
            'original_room': report.original_room,  # 替换为实际数据
            'original_class': report.original_class,  # 替换为实际数据
            'new_week': report.new_week,  # 替换为实际数据
            'new_class_time': report.new_class_time,  # 替换为实际数据
            'new_room': report.new_room,  # 替换为实际数据
            "time": report.updated_at.strftime("%Y年%m月%d日")
        }

        # 遍历文档中的所有段落
        for paragraph in doc.paragraphs:
            for run in paragraph.runs:
                self.replace_text_in_run(run, data)

        # 遍历文档中的所有表格
        for table in doc.tables:
            # 遍历表格中的所有行
            for row in table.rows:
                # 遍历行中的所有单元格
                for cell in row.cells:
                    # 遍历单元格中的所有段落
                    for paragraph in cell.paragraphs:
                        # 遍历段落中的所有运行
                        for run in paragraph.runs:
                            self.replace_text_in_run(run, data)

        # 保存文档到临时文件
        temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.docx')
        doc.save(temp_file.name)
        temp_file.seek(0)

        # 创建HTTP响应
        response = HttpResponse(temp_file.read(),
                                content_type='application/vnd.openxmlformats-officedocument.wordprocessingml.document')
        response['Content-Disposition'] = 'attachment; filename="word.docx"'
        return response

    def replace_text_in_run(self, run, data):
        text = run.text
        for key, value in data.items():
            placeholder = '$' + str(key)
            text = text.replace(placeholder, value)
        run.text = text
